package com.managed.bean;

import com.marlboroug.articlesbyauthors.ArticlesByAuthorsRemote;
import com.marlboroug.categories.CategoriesManagerRemote;
import com.marlboroug.entity.Articlesbyauthors;
import com.marlboroug.entity.Categories;
import com.marlboroug.entity.Parameters;
import com.marlboroug.parameters.ParametersManagerRemote;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

/**
 * Gestion de la bibliothèque.
 *
 * @author Cyril Schumacher
 */
@ManagedBean(name = "library")
@SessionScoped
public class LibraryBean implements Serializable {
    // <editor-fold defaultstate="collapsed" desc="Membres.">

    // <editor-fold defaultstate="collapsed" desc="Enterprise JavaBeans.">
    /**
     * Gestion des articles par auteur.
     */
    @EJB
    private ArticlesByAuthorsRemote _articlesByAuthorsManager;
    /**
     * Gestion des articles.
     */
    @EJB
    private ParametersManagerRemote _parametersManager;
    /**
     * Gestion des catégories.
     */
    @EJB
    private CategoriesManagerRemote _categoriesManager;
    // </editor-fold>

    /**
     * Liste des livres.
     */
    private List<Articlesbyauthors> _articles;
    /**
     * Liste complètes des livres.
     */
    private List<Articlesbyauthors> _allArticles;
    /**
     * Livre sélectionné.
     */
    private Articlesbyauthors _article;
    /**
     * Liste des catégories.
     */
    private List<Categories> _categories;
    /**
     * Identifiant de la catégorie utilisée.
     */
    private Long _category;
    /**
     * Index de la page actuelle.
     */
    private Integer _pageIndex;
    /**
     * Index maximum selon le nombre de livre.
     */
    private Integer _pageIndexMaximum;
    /**
     * Nombre de livres par page.
     */
    private Integer _getMaximumPerPage;
    /**
     * Mots-clés pour la recherche.
     */
    private String _searchText;
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Accesseurs/Mutateurs.">
    // <editor-fold defaultstate="collapsed" desc="Catégories.">
    /**
     * Obtient l'identifiant de la catégorie utilisée.
     *
     * @return Retourne l'identifiant de la catégorie.
     */
    public Long getCategory() {
        return _category;
    }

    /**
     * Définit l'identifiant de la catégorie utilisée.
     *
     * @param category Identifiant de la catégorie.
     */
    public void setCategory(Long category) {
        this._category = category;
    }

    /**
     * Obtient la liste des catégories.
     *
     * @return Retourne la liste des catégories.
     */
    public List<Categories> getCategories() {
        return _categories;
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Articles.">
    /**
     * Obtient la liste des livres.
     *
     * @return Retourne la liste des livres.
     */
    public List<Articlesbyauthors> getArticles() {
        return _articles;
    }

    /**
     * Obtient le nombre de livre disponible.
     *
     * @return Retourne le nombre.
     */
    public Integer getArticlesSize() {
        return _articles.size();
    }

    /**
     * Définit la liste des livres.
     *
     * @param articles Liste des livres.
     */
    public void setArticles(List<Articlesbyauthors> articles) {
        _articles = articles;
    }

    /**
     * Obtient l'article sélectionné par l'utilisateur.
     *
     * @return Retourne l'article.
     */
    public Articlesbyauthors getArticle() {
        return _article;
    }
    // </editor-fold>

    /**
     * Obtient les mots-clés pour la recherche.
     *
     * @return Retourne les mots-clés.
     */
    public String getSearchText() {
        return _searchText;
    }

    /**
     * Définit les mots-clés pour la recherche.
     *
     * @param _searchText Mots-clés.
     */
    public void setSearchText(String _searchText) {
        this._searchText = _searchText;
    }

    /**
     * Obtient une valeur indiquant si des livres peuvent être afficher.
     *
     * @return Retourne TRUE ou FALSE.
     */
    public Boolean hasNext() {
        return _pageIndex < _pageIndexMaximum;
    }

    /**
     * Obtient une valeur indiquant si des livres peuvent être afficher.
     *
     * @return Retourne TRUE ou FALSE.
     */
    public Boolean hasBack() {
        return _pageIndex > 0;
    }

    /**
     * Obtient une valeur indiquant si le livre est disponible.
     *
     * @return Retourne TRUE ou FALSE.
     */
    public Boolean isAvailable() {
        return (_article != null) && ((_article.getIdArticles().getState() != 3) || (_article.getIdArticles().getState() != 4));
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Méthodes.">
    // <editor-fold defaultstate="collapsed" desc="Privées.">
    /**
     * Récupère le nombre de livres par page.
     */
    private Integer _getMaximumPage() {
        // Nombre d'article maximum par page.
        int maximum = 0;

        // Parcours les résultats pour obtenir le nombre.
        List<Parameters> pages = _parametersManager.FindParameters();
        for (Parameters parameter : pages) {
            maximum = parameter.getArticlePage();
        }

        return maximum;
    }

    /**
     * Sélectionne une liste de livres selon l'index de la page.
     */
    private void _selectArticlePage() {
        // Récupère l'index de début et de fin selon l'index de la page actuelle.
        int fromIndex = _pageIndex * _getMaximumPerPage;
        int toIndex = fromIndex + _getMaximumPerPage;

        // Vérifie si l'on ne dépasse pas le nombre de livre.
        if (toIndex >= _allArticles.size()) {
            toIndex = _allArticles.size();
            if (fromIndex < 0) {
                fromIndex = 0;
            }
        }
        setArticles(_allArticles.subList(fromIndex, toIndex));
    }

    /**
     * Supprime les livres ayant un status "Supprimer".
     */
    private List<Articlesbyauthors> _deleteArticleSupressed(List<Articlesbyauthors> articles) {
        for (int i = 0; i < articles.size(); i++) {
            if (articles.get(i).getIdArticles().getState() == 5) {
                articles.remove(i);
            }
        }

        return articles;
    }

    /**
     * Calcule le nombre de page présente pour les livres.
     */
    private void _calculatePage() {
        // Retourne à la première page.
        _pageIndex = 0;
        _pageIndexMaximum = (int) ((double) _allArticles.size() / (double) _getMaximumPerPage);
        _selectArticlePage();
    }

    /**
     * Sélectionne tous les livres.
     */
    private void _selectAllPage() {
        // Récupère la liste des livres selon l'identifiant de la catégorie.
        List<Articlesbyauthors> articles = _articlesByAuthorsManager.ArticlesFindAll();
        _allArticles = _deleteArticleSupressed(articles);

        _calculatePage();
    }
    // </editor-fold>

    /**
     * Sélectionne la catégorie.
     */
    public void selectCategory() {
        if ((_category != null) & (_category != null)) {
            // Récupère la liste des livres selon l'identifiant de la catégorie.
            List<Articlesbyauthors> articles = _articlesByAuthorsManager.ArticlesFindCategory(_category);
            _allArticles = _deleteArticleSupressed(articles);
        } else {
            _selectAllPage();
        }

        _calculatePage();
    }

    /**
     * Sélectionne un article.
     *
     * @param article Article sélectionné.
     * @return Retourne une réponse pour le contrôleur JSF.
     */
    public String selectArticle(Articlesbyauthors article) {
        _article = article;
        return "success";
    }

    /**
     * Affiche les prochains articles.
     */
    public void next() {
        // Vérifie si on a pas atteint le nombre de page maximum.
        if (_pageIndexMaximum > _pageIndex) {
            _pageIndex++;
            _selectArticlePage();
        }

    }

    /**
     * Affiche les précédents articles.
     */
    public void back() {
        // Vérifie si l'index de la page est supérieure à 0.
        if (_pageIndex > 0) {
            _pageIndex--;
            _selectArticlePage();
        }
    }
    /**
     * Effectue une recherche selon des mots-clés.
     */
    public void search() {
        List<Articlesbyauthors> articles = _articlesByAuthorsManager.ArticlesFindCategoryWithKeyWord(_searchText);
        _allArticles = _deleteArticleSupressed(articles);
        
        _calculatePage();
    }
    // </editor-fold>

    // <editor-fold defaultstate="collapsed" desc="Initialisation de la classe.">
    /**
     * Initialise la classe après l'injection de dépendance.
     *
     * @see javax.annotation.PostConstruct
     */
    @PostConstruct
    public void initialize() {
        if (_pageIndex == null) {
            _pageIndex = 0;
        }

        if (_pageIndexMaximum == null) {
            _pageIndexMaximum = 0;
        }

        if (_categories == null) {
            _categories = new ArrayList<>(_categoriesManager.CategoriesFind());
        }

        if (_getMaximumPerPage == null) {
            _getMaximumPerPage = _getMaximumPage();
        }

        if (_articles == null) {
            _selectAllPage();
        }
    }
    // </editor-fold>
}
